/* 
● null 和 undefined
  ○ null: 表示一个空值, 它只有一个值null
  ○ undefined: 表示一个未定义的值, 它只有一个值undefined
  ○ 在非严格模式下:  null 和 undefined 是所有类型的子类型。 可以赋值给任意其它类型的变量
  ○ 在严格模式下: null和undefined不可以赋值给别的类型(any除外)
*/
let m1: null = null
let m2: undefined = undefined
let m3: number
// 在非严格模式下, null/undefined是所有类型的子类型
// m3 = m1  //error
// m3 = m2  //error

/* 
any: 任何类型，该类型会跳过类型检查，不太推荐使用。可以做任何操作
*/
let a: any
a = 5
a = 'hello'
let m4: number = a
a.test()

/* 
● unknown: 未知的类型, 与any类型类似, 但也有区别
  ○ 相同点: 都可以被赋值为任意类型值
  ○ 不同点: 
    ■ any类型可以赋值给其它任意类型, 而unknown类型不能赋值给非any的其它类型
    ■ any类型可以直接读取任意属性和调用任意方法, 但unknown类型不能直接使用, 需要先进行类型断言后才能使用
*/
let a1: any
let a2: unknown;
a1 = 'abc'
a2 = 'abc'
a1 = 3
a2 = 3
// let a3: number = a2   // error
let a3: number = a2 as number
// a2.test()  // error

/* 
never: 指示一个从不出现的类型。它表示永远不会有值的类型。常常用于函数永远不会正常结束的返回类型
*/

function throwError(error: string): never {
  throw new Error(error);
  // while (true) {

  // }
}

/* 
void: 没有任何类型, 经常用来定义函数没有返回值。
*/
function logMessage(message: string): void {
  console.log(message);
  // 不写return
  return undefined

  // return null  // 在非严格模式可以, 但在严格模式下 error
  // return '其它任意类型值都不可以'   // error
}